﻿﻿using System;
using System.Web;
using System.Collections;
using System.Text;

/// <summary>
/// Lớp phân trang.
/// </summary>
public class Paging
{
    private int totalCount = 0;    // tổng số record trả về từ CSDL.
    private int maxPage = 0;    // số trang lớn nhất.
    private int lowerBoundary;       // vùng số thấp.
    private int upperBoundary;       // vùng số cao.
    private string url;                 // lấy địa chỉ url của trang; 

    public Paging(int totalCount)
    {
        this.id = "paging"; // chưa dùng.
        this.queryString = "";
        this.param = "page";

        this.perPage = 10;
        this.currentPage = 1;

        this.linksBefore = 2;
        this.linksAfter = 2;

        this.firstText = " trang đầu";
        this.lastText = " trang cuối";
        this.NextText = " tiếp";
        this.PrevText = " trước";

        this.showFirst = false;
        this.showPrev = false;
        this.showNext = false;
        this.showLast = false;
        this.showMore = true;
        this.showPageNumber = true;

        this.currentMode = Mode.None; // tùy chọn: [none | combobox | editbox].
        this.inputInValid = "Số trang không tồn tại.";
        this.targetString = string.Empty;

        this.totalCount = totalCount;

        this.MaxPage();

        if (this.maxPage > linksAfter)
            this.ShowLast = true;

    }

    /// <summary>
    /// Hàm tính số trang lớn nhất, tính tròn tăng từ totalCount.
    /// </summary>
    private void MaxPage()
    {
        if (this.totalCount != 0)
        {
            this.maxPage = this.totalCount / this.PerPage;

            if ((this.maxPage * this.perPage) < totalCount)
            {
                this.maxPage += 1;
            }
        }
    }

    /// <summary>
    /// Hàm lấy địa chỉ url của trang đặt paging.
    /// </summary>
    /// <param name="pageNumber">số trang sẽ xem.</param>
    /// <returns>string</returns>
    private string TargetUrl(double pageNumber)
    {
        string url = "";
        int find = this.QueryString.IndexOf("?");

        if (find > 0)
        {
            url = this.QueryString + "&" + this.Param + "=" + pageNumber.ToString();
        }
        else
        {
            url = this.QueryString + "?" + this.Param + "=" + pageNumber.ToString();
        }

        return url;
    }

    /// <summary>
    /// Hàm xây dựng phân trang
    /// </summary>
    /// <returns>trả về chuỗi html với cấu trúc phân trang.</returns>
    public string BuildPaging()
    {
        StringBuilder outputPage = new StringBuilder();

        this.MaxPage();

        if (this.totalCount > this.PerPage)
        {
            /**
             * thêm hàm javascript xử lý khi CurrentMode là Combobox hay Editbox.
             */
            if (this.showPageNumber)
            {
                if (this.CurrentMode == Mode.Editbox)
                {
                    outputPage.Append("<script type=\"text/javascript\">");
                    outputPage.AppendLine();
                    outputPage.Append("window.addEvent('domready', function() {");
                    outputPage.AppendLine();
                    outputPage.Append("\tpagingEditbox(\"" + this.QueryString + "\", " + this.maxPage + ", \"" + this.Param + "\", \"" + this.InputInValid + "\");");
                    outputPage.AppendLine();
                    outputPage.Append("});</script>");
                    outputPage.AppendLine();
                }
                if (this.CurrentMode == Mode.Combobox)
                {
                    outputPage.Append("<script type=\"text/javascript\">");
                    outputPage.AppendLine();
                    outputPage.Append("window.addEvent('domready', function() {");
                    outputPage.AppendLine();
                    outputPage.Append("\tpagingCombobox(\"" + this.QueryString + "\", \"" + this.Param + "\")");
                    outputPage.AppendLine();
                    outputPage.Append("});</script>");
                    outputPage.AppendLine();
                }
            }

            /**
             * xét giá trị lại biến "currentPage" trang hiện tại đang xem.
             */
            //if (HttpContext.Current.Request.QueryString[this.Param] != null)
            //{
            //    this.currentPage = ConvertUtils.ToInt(HttpContext.Current.Request.QueryString[this.Param]);
            //}

            /**
﻿  ﻿       * tính vùng số (thấp) thoát ra khỏi liên kết trước trang hiện tại.
﻿  ﻿       * vd: 1 2 [3].
﻿  ﻿       */
            if ((this.CurrentPage - this.LinksBefore) < 1)
            {
                this.lowerBoundary = 1;
            }
            else
            {
                this.lowerBoundary = this.CurrentPage - this.LinksBefore;
            }

            /**
﻿  ﻿       * tính vùng số (cao) thoát ra khỏi liên kết sau trang hiện tại.
﻿  ﻿       * vd: [3] 4 5.
﻿  ﻿       */
            if ((this.CurrentPage + this.LinksAfter) > this.maxPage)
            {
                this.upperBoundary = this.maxPage;
            }
            else
            {
                this.upperBoundary = this.CurrentPage + this.LinksAfter;
            }

            /**
﻿  ﻿  ﻿       * tạo link từ miền giá trị lấy được trong khoảng giới hạn.
﻿  ﻿  ﻿       * khởi tạo mảng và truyền giá trị tương ứng vào mảng đó.
﻿  ﻿  ﻿       * vd: ... 1 2 [3] 4 5 ...
﻿  ﻿  ﻿       */
            ArrayList pageLinks = new ArrayList();

            if (this.ShowMore && (this.CurrentPage - this.LinksBefore) > 1)
            {
                pageLinks.Add("<span> ...</span>");
            }

            for (double i = this.lowerBoundary; i <= this.upperBoundary; i++)
            {
                if (this.CurrentPage == i)
                {
                    switch (this.CurrentMode)
                    {
                        case Mode.None:
                            pageLinks.Add("<li class=\"current\"><a href=\"#\">" + i + "</a></li>");
                            break;
                        case Mode.Combobox:
                            StringBuilder combobox = new StringBuilder();
                            combobox.Append("<select id=\"paging-mode-combobox\" class=\"current-combobox\">");
                            for (double j = 1; j <= this.maxPage; j++)
                            {
                                combobox.Append("<option value=\"" + j + "\"");
                                if (this.CurrentPage == j)
                                {
                                    combobox.Append(" selected=\"selected\"");
                                }
                                combobox.Append(">" + j + "</option>");
                                combobox.AppendLine();
                            }
                            combobox.Append("</select>");
                            combobox.AppendLine();
                            pageLinks.Add(combobox.ToString());
                            break;
                        case Mode.Editbox:
                            string editbox = "<input type=\"text\" id=\"paging-mode-editbox\" class=\"current-editbox\" value=\"" + i + "\">";
                            pageLinks.Add(editbox);
                            break;
                        default:
                            pageLinks.Add("<li class=\"current\"><a href=\"#\">" + i + "</a></li>");
                            break;
                    }
                }
                else
                {

                    pageLinks.Add("<li><a href=\"" + this.TargetUrl(i) + "\" " + this.targetString + ">" + i + "</a></li>");

                }
            }

            if (this.ShowMore && (this.CurrentPage + this.LinksAfter) < this.maxPage)
            {
                pageLinks.Add("<span> ...</span>");
            }

            /**
﻿           * tạo link: first | prev | next | last.
﻿           */
            string firstLink = null;
            string prevLink = null;
            string nextLink = null;
            string lastLink = null;

            if (this.CurrentPage != 1)
            {
                firstLink = "<li><a title=\"Trang Đầu\" href=\"" + this.TargetUrl(1) + "\" >" + this.FirstText + "</a></li>";
                prevLink = "<li><a title=\"Trang Trước\" href=\"" + this.TargetUrl(this.CurrentPage - 1) + "\">" + this.prevText + "</a></li>";
            }
            if (this.CurrentPage != this.maxPage)
            {
                nextLink = "<li><a title=\"Trang Kế\" href=\"" + this.TargetUrl(this.CurrentPage + 1) + "\">" + this.nextText + "</a></li>";
                lastLink = "<li><a title=\"Trang Cuối\" style=\"font-size:8pt;\" href=\"" + this.TargetUrl(this.maxPage) + "\">" + this.lastText + "</a></li>";
            }

            /**
﻿               * kiểm tra điều kiện và truyền phần tử vào thẻ chứa paging. 
﻿               * một số dạng paging sau:
﻿               * Ký hiệu: X = [none | combobox | editbox]
﻿               * 1: F P ... 1 2 [X] 4 5 ... N L
﻿               * 2: ... 1 2 [X] 4 5 ...
﻿               * 3: 1 2 [X] 4 5
﻿               * 4: F P N L
﻿               * 5: [X] N L
﻿               * 6: N L
﻿               * 7: P N
﻿               * 8: ..vv..
﻿               */

            if (this.ShowFirst && firstLink != null)
            {
                outputPage.Append(firstLink);
                outputPage.AppendLine();
            }
            if (this.ShowPrev && prevLink != null)
            {
                outputPage.Append(prevLink);
                outputPage.AppendLine();
            }

            if (this.ShowPageNumber && pageLinks.Count > 0)
            {
                foreach (string link in pageLinks)
                {
                    outputPage.Append(link);
                    outputPage.AppendLine();
                }
            }

            if (this.ShowNext && nextLink != null)
            {
                outputPage.Append(nextLink);
                outputPage.AppendLine();
            }
            if (this.ShowLast && lastLink != null)
            {
                outputPage.Append(lastLink);
                outputPage.AppendLine();
            }
        }

        return outputPage.ToString();
    }

    /// <summary>
    /// Thuộc tính cho trang.
    /// </summary>
    #region Paging Properties
    private string id;
    private string queryString;
    private string param;
    private int perPage;
    private int currentPage;
    private int linksBefore;
    private int linksAfter;
    private string firstText;
    private string prevText;
    private string nextText;
    private string lastText;
    private bool showFirst;
    private bool showPrev;
    private bool showNext;
    private bool showLast;
    private bool showMore;
    private bool showPageNumber;
    private Mode currentMode;
    private string inputInValid;
    private string targetString;
    /// <summary>
    /// ID của thẻ div chứa paging.
    /// </summary>
    public string ID
    {
        get { return id; }
        set { id = value; }
    }
    /// <summary>
    /// Trang liên kết. Chấp nhận 2 dạng sau:
    /// 1: "".
    /// 2: filename.aspx?query.
    /// </summary>
    public string QueryString
    {
        get { return queryString; }
        set { queryString = value; }
    }
    /// <summary>
    /// Biến QueryString.
    /// </summary>
    public string Param
    {
        get { return param; }
        set { param = value; }
    }
    /// <summary>
    /// Số dòng hiển thị trên một trang .
    /// </summary>
    public int PerPage
    {
        get { return perPage; }
        set { perPage = value; }
    }
    /// <summary>
    /// Số của trang hiện tại.
    /// </summary>
    public int CurrentPage
    {
        get { return currentPage; }
        set { currentPage = value; }
    }
    /// <summary>
    /// Số link trước trang hiện tại.
    /// </summary>
    public int LinksBefore
    {
        get { return linksBefore; }
        set { linksBefore = value; }
    }
    /// <summary>
    /// Số link sau trang hiện tai.
    /// </summary>
    public int LinksAfter
    {
        get { return linksAfter; }
        set { linksAfter = value; }
    }
    /// <summary>
    /// Text hiển thị cho link về trang đầu tiên.
    /// </summary>
    public string FirstText
    {
        get { return firstText; }
        set { firstText = value; }
    }
    /// <summary>
    /// Text hiển thị cho link tới trang trước.
    /// </summary>
    public string PrevText
    {
        get { return prevText; }
        set { prevText = value; }
    }
    /// <summary>
    /// Text hiển thị cho link tới trang kế tiếp.
    /// </summary>
    public string NextText
    {
        get { return nextText; }
        set { nextText = value; }
    }
    /// <summary>
    /// Text hiển thị cho link tới trang cuối.
    /// </summary>
    public string LastText
    {
        get { return lastText; }
        set { lastText = value; }
    }
    /// <summary>
    /// Cho phép hiển thị link về trang đầu tiên.
    /// </summary>
    public bool ShowFirst
    {
        get { return showFirst; }
        set { showFirst = value; }
    }
    /// <summary>
    /// Cho phép hiển thị link về trang trước.
    /// </summary>
    public bool ShowPrev
    {
        get { return showPrev; }
        set { showPrev = value; }
    }
    /// <summary>
    /// Cho phép hiển thị link tới trang kế tiếp.
    /// </summary>
    public bool ShowNext
    {
        get { return showNext; }
        set { showNext = value; }
    }
    /// <summary>
    /// Cho phép hiển thị link tới trang cuối.
    /// </summary>
    public bool ShowLast
    {
        get { return showLast; }
        set { showLast = value; }
    }
    /// <summary>
    /// Cho phép hiển thị thông báo tồn tại trang ngoài vùng [...].
    /// </summary>
    public bool ShowMore
    {
        get { return showMore; }
        set { showMore = value; }
    }
    /// <summary>
    /// Cho phép hiển thị link số trang trong vùng.
    /// </summary>
    public bool ShowPageNumber
    {
        get { return showPageNumber; }
        set { showPageNumber = value; }
    }
    /// <summary>
    /// Chế độ tùy chọn cho trang hiện tại.
    /// </summary>
    public Mode CurrentMode
    {
        get { return currentMode; }
        set { currentMode = value; }
    }
    /// <summary>
    /// Chuỗi thông báo khi chọn chế độ Mode.Editbox không hợp lệ.
    /// </summary>
    public string InputInValid
    {
        get { return inputInValid; }
        set { inputInValid = value; }
    }
    /// <summary>
    /// Chuỗi thuộc tính target cho tag A, ví dụ: target="_blank"
    /// </summary>
    public string TargetString
    {
        get { return targetString; }
        set { targetString = value; }
    }
    #endregion
}